// HostMatrix.cpp
#include "XMatrix.hpp"
#include "multiple.cuh"
#include <cstdio>
#include <stdexcept>

// 构造函数
XMatrix::XMatrix(int height, int width) : height(height), width(width) {
  elements = std::shared_ptr<float[]>(new float[width * height]);
  if (elements == nullptr) {
    throw std::runtime_error("Memory allocation failed for HostMatrix");
  }
}

// 获取矩阵宽度
int XMatrix::getWidth() const { return width; }

// 获取矩阵高度
int XMatrix::getHeight() const { return height; }

// 填充为递增序列
void XMatrix::fill_range() {
  for (int i = 0; i < width * height; ++i) {
    elements[i] = static_cast<float>(i + 1);
  }
}

// 填充为1
void XMatrix::fill_one() { std::fill_n(elements.get(), width * height, 1.0f); }
// 填充为0
void XMatrix::fill_zero() { std::fill_n(elements.get(), width * height, 0.0f); }
// 将外部数组填充到矩阵
void XMatrix::fill_array(float array[], bool transpose) {
  int max_size = width * height;
  if (transpose) {
    // 如果是列优先填充
    for (int j = 0; j < width; ++j) {
      for (int i = 0; i < height; ++i) {
        elements[i * width + j] = array[i * width + j];
      }
    }
  } else {
    // 默认行优先填充
    for (int i = 0; i < max_size; ++i) {
      elements[i] = array[i];
    }
  }
}

// 将外部数组填充到矩阵
void XMatrix::fill_array(std::vector<float> &array, bool transpose) {
  int max_size = width * height;
  if (transpose) {
    // 如果是列优先填充
    for (int j = 0; j < width; ++j) {
      for (int i = 0; i < height; ++i) {
        elements[i * width + j] = array[i * width + j];
      }
    }
  } else {
    // 默认行优先填充
    for (int i = 0; i < max_size; ++i) {
      elements[i] = array[i];
    }
  }
}

// 将外部数组填充到矩阵
void XMatrix::fill_array(std::vector<std::vector<float>> &array,
                         bool transpose) {
  int max_size = width * height;
  if (transpose) {
    // 如果是列优先填充
    for (int j = 0; j < width; ++j) {
      for (int i = 0; i < height; ++i) {
        elements[i * width + j] = array[i][j];
      }
    }
  } else {
    // 默认行优先填充
    for (int i = 0; i < height; ++i) {
      for (int j = 0; j < width; ++j) {
        elements[i * width + j] = array[i][j];
      }
    }
  }
}

// 打印矩阵内容
void XMatrix::print() const {
  for (int i = 0; i < height; ++i) {
    for (int j = 0; j < width; ++j) {
      printf("%f ", elements[i * width + j]);
    }
    printf("\n");
  }
}

XMatrix operator*(XMatrix &hostA, XMatrix &hostB) {

  XMatrix hostC(hostA.getHeight(), hostB.getWidth()); // 4行1列
  if (hostA.getWidth() != hostB.getHeight()) {
    throw std::runtime_error(
        "Matrix dimensions do not match for multiplication");
  }
  _PlainMatrix A{hostA.getWidth(), hostA.getHeight(), hostA.get_raw()};
  _PlainMatrix B{hostB.getWidth(), hostB.getHeight(), hostB.get_raw()};
  _PlainMatrix C{hostC.getWidth(), hostC.getHeight(), hostC.get_raw()};

  CUDAMatMul(A, B, C);

  return hostC;
}